;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; \brief	自己写汇编boot，并用汇编从串口输出Hello world
; \note		File format: UTF-8
; \author	将狼才鲸
; \date		2022-10-24
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;$NOPRINT	; 阻止编译器生成列表文件，已屏蔽

;================================ 头文件 =======================================
$INCLUDE (R8051XC2.INC)		; 文件包含，芯片SFR特殊功能寄存器定义
$INCLUDE (REG_USER.INC)		; 你正在使用的8051芯片特有的SFR寄存器，因为每个芯片不一样，我这里使用虚拟的寄存器
$INCLUDE (MACRO_FUNC.INC)	; 自定义的宏定义函数
$INCLUDE (USER_CONFIG.INC)	; 做配置用的宏定义
$INCLUDE (IRQ_ISR.ASM)		; 中断处理ISR，中断上半部
$INCLUDE (STARTUP.ASM)		; 用户执行的第一块汇编代码，主程序入口在STARTUP.ASM当中
; 板子上电后第一条执行的0地址的代码就在这里面，中断处理函数的入口也在这里面
$INCLUDE (VECTOR_IRQ.ASM)	; 程序上电后第一个执行的复位，中断和异常的入口
$INCLUDE (COMMON_FUNC.ASM)	; 一些共用的汇编函数，可以在C语言源码中调用
$INCLUDE (COMMON_FUNC.INC)	; 一些共用的汇编宏定义函数，可以在C语言源码中调用

;EXTERN CODE(_Main) ; 声明main.c中的main()函数，该函数在汇编中名为_Main

;;
; 程序不是一开始就直接在这里执行的，而是在STARTUP.ASM里面调用到这里来的，STARTUP.ASM才是程序的默认入口
;;
_RESET_MAIN:
	LCALL PRINT_UART_INFO	; 调用汇编函数，先从串口打印一点东西，这个函数在本文件后面定义
	;LCALL _Main			; 调用C语言中的main()函数
_loop:
	LCALL _loop				; 死循环，防止程序执行完后重复执行
	NOP

;;
; 定义字符串常量
;;
INFO_PRINT_1:
DB 'Hello world!....' ; 总共16字节数据
INFO1_LEN EQU 10H

;;
; \brief	串口1发送字符串数据
; \param	无
;;
PRINT_UART_INFO:
	;LCALL _hw_init_uart0 ; TODO，加到别的初始化里面去
	MOV  A, R0
	PUSH ACC		; 压栈R0
	MOV  R0, #00H	; int i = 0;
PRINT_LOOP_1:
	MOV  DPTR, #INFO_PRINT_1	; 把字符串指针放入DPL DPH数据指针中
	MOV  A, R0
	MOVC A, @A+DPTR			; A = *(A + DPTR), 整条语句是一条固定的指令
	LCALL UART0_SEND		; 从串口发送1字节
	INC  R0			; R0++
	;CJNE R0, #10H, PRINT_LOOP_1
	CJNE R0, #INFO1_LEN, PRINT_LOOP_1	; 比较累加器和立即数,不相等则转移
	POP  ACC
	MOV  R0, A		; 弹栈
	RET				; 函数返回

;;
; \brief	串口0发送1字节数据
; \param	A	1字节数据
;;
UART0_SEND:
	MOV S0BUF, A
LB_SEND_WAIT:	; 等待最后一个bit发送完成
	MOV A, S0CON
	ANL A, #02H
	JZ  LB_SEND_WAIT	; A为0则跳转
	ANL S0CON, #0FDH
	RET

;;
; \brief	初始化串口0
_hw_init_uart0:
	; S0CON: D7~D0: SM0 SM1 SM2 REN      TB8 RB8 TI RI
	;               通讯设置    接收使能 数据位9 收发中断
	;MOV S0CON, #50H	; 1个起始位0，8个数据位和1个停止位1，接收使能
	; Keil使用模拟器调试时，不初始化串口也能从串口收发数据
	NOP
	RET

	END